package com.atom.app.mvi.ui.rd

import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.ClickableText
import androidx.compose.material.Icon
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material3.Button
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.MutableLiveData
import com.atom.app.mvi.AppModel
import com.atom.app.mvi.R
import com.atom.app.mvi.net.bean.LoginRequest
import com.atom.app.mvi.net.bean.LoginResponse
import com.atom.app.mvi.ui.compose.view.MenuActivity
import com.atom.app.mvi.utils.RsaUtils
import com.atom.app.mvi.utils.toast
import com.atom.module.logger.Logger
import com.atom.module.mvi.android.lifecycle.createDestroy
import com.atom.module.mvi.android.view.MVIActivity
import com.atom.module.mvi.binder.Binder
import com.atom.module.mvi.binder.using
import com.atom.module.mvi.core.element.Actor
import com.atom.module.mvi.core.element.Reducer
import com.atom.module.mvi.core.feature.ActorReducerFeature
import com.atom.module.mvi.core.feature.ReducerFeature
import com.atom.module.mvi.util.DistinctUntilChangedLiveData
import com.atom.module.mvi.util.Result2
import com.atom.module.mvi.util.combineLatest
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.*

sealed class LoginUIEvent {
    object LoginEvent : LoginUIEvent()
    data class LoginByPassword(val username: String, val password: String) : LoginUIEvent()
    object LoginByVerify : LoginUIEvent()
}

data class ViewModel(
    var loginState: Int, var loginResult: LoginResponse.Data? = null
)

private class Feature : ReducerFeature<LoginUIEvent, Feature.State, Nothing>(
    initialState = State(), reducer = ReducerImpl()
) {
    data class State(
        val loginState: Int = 0
    )

    class ReducerImpl : Reducer<State, LoginUIEvent> {
        override fun invoke(state: State, effect: LoginUIEvent): State {
            when (effect) {
                is LoginUIEvent.LoginEvent -> {
                    val new = state.copy(loginState = state.loginState + 1)
                    Logger.e(new, state, new == state)
                    return new
                }
                else -> {
                    return state
                }
            }
        }
    }
}

private class NetFeature : ActorReducerFeature<LoginUIEvent, NetFeature.Effect, NetFeature.State, Nothing>(
    initialState = State(), reducer = ReducerImpl(), actor = ActorImpl()
) {
    data class State(
        val date: LoginResponse.Data? = null
    )

    sealed class Effect {
        object None : Effect()
        object StartLoading : Effect()
        object ErrorLoading : Effect()
        data class Result(val date: LoginResponse.Data) : Effect()
    }

    class ActorImpl : Actor<State, LoginUIEvent, Effect> {
        val appModel = AppModel
        override fun invoke(state: State, action: LoginUIEvent): Observable<out Effect> {
            when (action) {
                is LoginUIEvent.LoginByPassword -> {
                    return appModel.netApi.postGetRSAKey().flatMap {
                        val rasPassWord: String = RsaUtils.encryptDataByPublicKey(
                            action.password.toByteArray(), RsaUtils.keyStrToPublicKey(it.data)
                        )
                        appModel.netApi.postLoginData(
                            LoginRequest(
                                action.username, rasPassWord, it.data
                            )
                        )
                    }.map {
                        Effect.Result(it.data)
                    }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                }
                else -> {
                    return Observable.just(Effect.None).subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                }
            }
        }
    }

    class ReducerImpl : Reducer<State, Effect> {
        override fun invoke(state: State, effect: Effect): State {
            when (effect) {
                is Effect.Result -> {
                    return state.copy(date = effect.date)
                }
                else -> {
                    return state
                }
            }
        }
    }
}

private object ViewModelTransform : (Result2<Feature.State, NetFeature.State>) -> ViewModel {
    override fun invoke(p1: Result2<Feature.State, NetFeature.State>): ViewModel {
        return ViewModel(p1.t1.loginState, p1.t2.date)
    }
}

class LoginActivity : MVIActivity<LoginUIEvent, ViewModel>() {


    private val viewLiveData = DistinctUntilChangedLiveData<ViewModel>()


    override fun binder(): Binder {
       return this.lifecycle.createDestroy {
           val feature = Feature()
           val netFeature = NetFeature()
           this.bind(combineLatest(feature, netFeature) to this@LoginActivity using ViewModelTransform)
           this.bind(this@LoginActivity to feature)
           this.bind(this@LoginActivity to netFeature)
       }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { loginContentView() }
    }

    @Preview
    @Composable
    fun preView() {
        loginContentView()
    }

    @Composable
    private fun loginContentView() {
        Surface(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.Red),
            color = Color.White,
            contentColor = Color.Blue
        ) {
            Column(modifier = Modifier.padding(start = 24.dp, end = 24.dp)) {
                Spacer(modifier = Modifier.height(56.dp))
                Icon(
                    painter = painterResource(id = R.mipmap.icon_launcher),
                    contentDescription = "",
                    tint = Color.Unspecified,
                    modifier = Modifier.size(36.dp)
                )
                Spacer(modifier = Modifier.height(12.dp))
                val isPhoneLogin: MutableState<Boolean> = remember {
                    mutableStateOf(false)
                }
                LaunchedEffect(key1 = isPhoneLogin.value, block = {
                    Logger.e("LaunchedEffect", " 切换登录方式 ")
                })
                if (isPhoneLogin.value) {
                    PhoneLogin(isPhoneLogin)
                } else {
                    PasswordLogin(isPhoneLogin)
                }
                Spacer(modifier = Modifier.weight(1f))
                Text(
                    text = "其他登录方式", modifier = Modifier
                        .fillMaxWidth()
                        .wrapContentWidth(align = Alignment.CenterHorizontally)
                )
                Icon(painter = painterResource(id = R.mipmap.icon_launcher),
                    contentDescription = "",
                    tint = Color.Unspecified,
                    modifier = Modifier
                        .fillMaxWidth()
                        .wrapContentWidth(align = Alignment.CenterHorizontally)
                        .clickable {
                            onNext(LoginUIEvent.LoginEvent)
                        })
                Spacer(modifier = Modifier.height(40.dp))
            }
        }

        val observeAsState = viewLiveData.observeAsState()

        LaunchedEffect(key1 = observeAsState.value, block = {
            Logger.e("LaunchedEffect key1 = observeAsState.value 变化了 ${observeAsState.value}")
        })
    }

    @Composable
    private fun PasswordLogin(switchLogin: MutableState<Boolean>) {
        var phone by remember {
            mutableStateOf("17572695197")
        }
        var password by remember {
            mutableStateOf("a123456")
        }
        Column(modifier = Modifier.fillMaxWidth()) {
            Text(text = "密码登录", fontSize = 24.sp)
            Spacer(modifier = Modifier.height(38.dp))
            TextField(modifier = Modifier.fillMaxWidth(), value = phone, onValueChange = { v ->
                Logger.e("手机号:${v}")
                phone = v
            }, placeholder = {
                Text(text = "手机号/邮箱")
            }, trailingIcon = {
                Icon(
                    modifier = Modifier.clickable {
                        Toast.makeText(this@LoginActivity, "icon 1", Toast.LENGTH_SHORT).show()
                    },
                    painter = painterResource(id = R.mipmap.icon_launcher),
                    contentDescription = "",
                    tint = Color.Unspecified
                )
            }, leadingIcon = {
                Icon(
                    modifier = Modifier.clickable {
                        Toast.makeText(this@LoginActivity, "icon 2", Toast.LENGTH_SHORT).show()
                    },
                    painter = painterResource(id = R.mipmap.icon_launcher),
                    contentDescription = "",
                    tint = Color.Unspecified
                )
            })

            Spacer(modifier = Modifier.height(36.dp))

            TextField(
                modifier = Modifier.fillMaxWidth(),
                value = password,
                onValueChange = { v -> password = v },
                placeholder = {
                    Text(text = "密码")
                },
                trailingIcon = {
                    Icon(
                        modifier = Modifier.clickable {
                            Toast.makeText(this@LoginActivity, "icon 1", Toast.LENGTH_SHORT).show()
                        },
                        painter = painterResource(id = R.mipmap.icon_launcher),
                        contentDescription = "",
                        tint = Color.Unspecified
                    )
                },
                leadingIcon = {
                    Icon(
                        modifier = Modifier.clickable {
                            Toast.makeText(this@LoginActivity, "icon 2", Toast.LENGTH_SHORT).show()
                        },
                        painter = painterResource(id = R.mipmap.icon_launcher),
                        contentDescription = "",
                        tint = Color.Unspecified
                    )
                },
                visualTransformation = PasswordVisualTransformation()
            )

            Spacer(modifier = Modifier.height(40.dp))
            Row(modifier = Modifier.fillMaxWidth()) {
                Icon(
                    painter = painterResource(id = R.mipmap.icon_launcher),
                    modifier = Modifier
                        .size(20.dp)
                        .clickable { },
                    contentDescription = null,
                    tint = Color.Unspecified
                )
                val annotatedText = buildAnnotatedString {
                    append("我已阅读并同意:")
                    //-服务协议,隐私政策
                    pushStringAnnotation(tag = "URL", annotation = "点击服务和隐私")
                    withStyle(
                        style = SpanStyle(
                            color = Color.Blue, fontWeight = FontWeight.Bold
                        )
                    ) {
                        append("服务协议,隐私政策")
                    }
                    pop()
                    //-法律声明
                    pushStringAnnotation(tag = "URL", annotation = "法律声明")
                    withStyle(
                        style = SpanStyle(
                            color = Color.Blue, fontWeight = FontWeight.Bold
                        )
                    ) {
                        append("法律声明")
                    }
                    pop()
                }
                ClickableText(text = annotatedText, onClick = { offset ->
                    annotatedText.getStringAnnotations(
                        tag = "URL", start = offset, end = offset
                    ).firstOrNull()?.also {
                        Toast.makeText(this@LoginActivity, it.item, Toast.LENGTH_SHORT).show()
                    }
                })
            }

            Spacer(modifier = Modifier.height(10.dp))
            Button(modifier = Modifier.fillMaxWidth(), onClick = {
                this@LoginActivity.toast("点击了登录按钮")
                if (phone.isEmpty()) return@Button
                if (password.isEmpty()) return@Button
                onNext(LoginUIEvent.LoginByPassword(phone , password))
            }) {
                Text(text = "登录")
            }
            Spacer(modifier = Modifier.height(15.dp))
            Row(modifier = Modifier.fillMaxWidth()) {
                Text(text = "短信验证码登录", modifier = Modifier.clickable {
                    //  用户切换密码和验证码登录
                    switchLogin.value = true
                })
                Spacer(modifier = Modifier.weight(1f))
                Text(text = "忘记密码")
            }
        }
    }

    @Composable
    private fun PhoneLogin(switchLogin: MutableState<Boolean>) {
        Column(modifier = Modifier.fillMaxWidth()) {
            Text(text = "短信验证码登录", fontSize = 24.sp)
            Spacer(modifier = Modifier.height(38.dp))
            TextField(modifier = Modifier.fillMaxWidth(),
                value = "",
                onValueChange = { v -> },
                placeholder = {
                    Text(text = "请输入手机号")
                },
                trailingIcon = {
                    Row {
                        Icon(modifier = Modifier
                            .clickable {
                                Toast
                                    .makeText(this@LoginActivity, "icon 1", Toast.LENGTH_SHORT)
                                    .show()
                            }
                            .size(20.dp),
                            painter = painterResource(id = R.mipmap.icon_launcher),
                            contentDescription = "",
                            tint = Color.Unspecified)
                        Text(text = "获取验证码", modifier = Modifier.clickable { })
                    }
                },
                leadingIcon = {
                    Text(text = "+86")
                    // 设置一个view
                    
                })

            Spacer(modifier = Modifier.height(36.dp))

            TextField(
                modifier = Modifier.fillMaxWidth(),
                value = "",
                onValueChange = { v -> },
                placeholder = {
                    Text(text = "请输入验证码")
                },
                trailingIcon = {
                    Icon(modifier = Modifier
                        .clickable {
                            Toast
                                .makeText(this@LoginActivity, "icon 1", Toast.LENGTH_SHORT)
                                .show()
                        }
                        .size(20.dp),
                        painter = painterResource(id = R.mipmap.icon_launcher),
                        contentDescription = "",
                        tint = Color.Unspecified)
                },
                leadingIcon = {
                    Text(text = "验证码")
                },
                visualTransformation = PasswordVisualTransformation()
            )

            Spacer(modifier = Modifier.height(40.dp))
            Row(modifier = Modifier.fillMaxWidth()) {
                Icon(
                    painter = painterResource(id = R.mipmap.icon_launcher),
                    modifier = Modifier
                        .size(20.dp)
                        .clickable { },
                    contentDescription = null,
                    tint = Color.Unspecified
                )
                val annotatedText = buildAnnotatedString {
                    append("我已阅读并同意:")
                    //-服务协议,隐私政策
                    pushStringAnnotation(tag = "URL", annotation = "点击服务和隐私")
                    withStyle(
                        style = SpanStyle(
                            color = Color.Blue, fontWeight = FontWeight.Bold
                        )
                    ) {
                        append("服务协议,隐私政策")
                    }
                    pop()
                    //-法律声明
                    pushStringAnnotation(tag = "URL", annotation = "法律声明")
                    withStyle(
                        style = SpanStyle(
                            color = Color.Blue, fontWeight = FontWeight.Bold
                        )
                    ) {
                        append("法律声明")
                    }
                    pop()
                }
                ClickableText(text = annotatedText, onClick = { offset ->
                    annotatedText.getStringAnnotations(
                        tag = "URL", start = offset, end = offset
                    ).firstOrNull()?.also {
                        Toast.makeText(this@LoginActivity, it.item, Toast.LENGTH_SHORT).show()
                    }
                })
            }
            Spacer(modifier = Modifier.height(10.dp))
            Button(modifier = Modifier.fillMaxWidth(), onClick = {
                this@LoginActivity.toast("点击了登录按钮")
            }) {
                Text(text = "验证登录", color = Color.White)
            }
            Spacer(modifier = Modifier.height(15.dp))
            Text(text = "密码登录",
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentWidth(align = Alignment.CenterHorizontally)
                    .clickable {
                        //  用户切换密码和验证码登录
                        switchLogin.value = false
                    })
        }
    }


    override fun accept(t: ViewModel) {
        Logger.e("accept", t)
        t.loginResult?.also {
            Logger.e("登录成功", it)
            // 执行界面跳转
            startActivity(Intent(this@LoginActivity , LaunchActivity::class.java))
            return
        }

        viewLiveData.setValue(t)
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
            startActivity(Intent(this@LoginActivity , LaunchActivity::class.java))
        }
        if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
            startActivity(Intent(this@LoginActivity , MenuActivity::class.java))
        }
        return super.onKeyDown(keyCode, event)
    }
}
